package com.fingard.dsp.bank.directbank.fubon01;

import com.fingard.dsp.bank.directbank.DirectBase;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqBatPayRec;
import com.fingard.io.FileHelper;
import com.fingard.net.ITcpClient;
import com.fingard.net.TcpPortClient;
import com.fingard.net.TcpReceiver;
import com.fingard.text.StringHelper;
import com.fingard.xml.XmlTextWriter;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpConnectionParams;

import javax.net.ssl.SSLContext;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

public class FUBON01Base extends DirectBase implements ITcpClient {
    private String separator = "|";

    public Map<String, Object> writerPayFileContext(ReqBatPayRec p_req1988) throws Exception {
        //交易流水|付款账号/卡号|付款人名称|绑定账号|有效证件种类|有效证件种号|收款账号/卡号|收款人名称|收款行行号|收款行名|币种|交易金额|转账类型|业务代码|手续费|附言|
        Map<String, Object> resultAndfileContext = new HashMap<String, Object>();
        StringBuilder msgXml = new StringBuilder();
        int tmpCount = 0;
        while (p_req1988.readRecord()) {
            tmpCount++;
            String dateTime = p_req1988.readedDetail.payDate.replaceAll("-", "") + p_req1988.readedDetail.payTime.replaceAll(":", "");
            msgXml.append(dateTime).append(p_req1988.readedDetail.askNumber).append(separator);//日期YYYYMMDDhhmmss+每笔的批次内流水号
            msgXml.append(p_req1988.readedDetail.payAct).append(separator);//付款账号/卡号
            msgXml.append(p_req1988.readedDetail.payName).append(separator);//付款人名称
            msgXml.append(separator);//？？？绑定账号
            msgXml.append(separator);//？？？有效证件种类
            msgXml.append(separator);//？？？有效证件种号
            msgXml.append(p_req1988.readedDetail.recAct).append(separator);//收款账号/卡号
            msgXml.append(p_req1988.readedDetail.recName).append(separator);//收款人名称
            msgXml.append(p_req1988.readedDetail.cnapsCode).append(separator);//收款行号
            msgXml.append(p_req1988.readedDetail.cnapsName).append(separator);//收款行名
            msgXml.append(getBankConfig().getMapValueByKey("currencyMapping2", p_req1988.readedDetail.payCur)).append(separator);//币种 默认CNY
            msgXml.append(p_req1988.readedDetail.payAmount).append(separator);//交易金额
            if(p_req1988.readedDetail.sameBnk.equals("1")){//转账类型 跨行0 同行2  0普通汇兑，1代扣，2还款，3提现
                //同行
                msgXml.append("2").append(separator);
            }else {
                //跨行
                msgXml.append("0").append(separator);
            }
            msgXml.append("TMS").append(separator);//业务代码
            msgXml.append(separator);//手续费 默认：0
            msgXml.append(p_req1988.readedDetail.abstractATS).append(separator);//附言(对账码)
            msgXml.append("\r\n");
        }
        if (tmpCount != Integer.parseInt(p_req1988.totalNum)) {
            resultAndfileContext.put("result", "false");
        } else {
            resultAndfileContext.put("result", "true");
        }
        resultAndfileContext.put("fileContext", msgXml);
        return resultAndfileContext;
    }

    protected String writeGxpHeader(FUBON01Header fubon01Header, String reqStr) throws Exception {
        StringBuilder gxpHeader = new StringBuilder();
        gxpHeader.append(fubon01Header.glbTrSeq);//全局流水号 请求方系统编号（6）+交易类型（2）+服务方系统编号（6）+自然日日期（YYYYMMDD）+预留（2）+8位长自定义流水号
        gxpHeader.append(fubon01Header.sndId);//请求方Id
        gxpHeader.append(fubon01Header.pkgType);//Q:请求 A:应答
        gxpHeader.append(fubon01Header.recvId);//服务方Id
        String tmpEAIreqNo = "";
        tmpEAIreqNo = String.format("%1$-25s", tmpEAIreqNo);
        gxpHeader.append(tmpEAIreqNo);//EAI流水号 网关填写，客户请求为空
        gxpHeader.append(fubon01Header.pkgFmt);//01: xml
        gxpHeader.append(fubon01Header.methdNm);//GXP接口码 GXP服务编码（见《数据映射关系》），交易穿透缺省填“00000000”
        String tmpRespCode = "";
        tmpRespCode = String.format("%1$-5s", tmpRespCode);
        gxpHeader.append(tmpRespCode);//RespCode
        gxpHeader.append(fubon01Header.chnlId);//供核心记账使用，缺省填“00000000”
        gxpHeader.append(fubon01Header.sgMsgFlg);//签名标志 是否产生签名信息：U:有 N:没有
        gxpHeader.append(String.format("%1$-24s", fubon01Header.signMsg));
        fubon01Header.remark1 = new String(HSDES.genMAC(reqStr.getBytes(getCharset()))).substring(0, 4);
        gxpHeader.append(String.format("%1$-4s", fubon01Header.remark1));//需要验MAC的渠道比输：MAC值  测试环境暂时不校验
        gxpHeader.append(String.format("%1$-48s", getIpAddress()));//前15位为发起方IP地址
        gxpHeader.append(String.format("%1$-100s", ""));
        gxpHeader.append(String.format("%1$-200s", ""));

        return gxpHeader.toString();
    }

    protected void writeCommonHeader(XmlTextWriter xmlWriter, FUBON01Header fubon01Header) throws Exception {
        xmlWriter.writeStartElement("service");
        xmlWriter.writeStartElement("GapsAppHead");//公共应用头部
        xmlWriter.writeElementString("ServiceCode", fubon01Header.ServiceCode);//服务代码 服务唯一标识，由EAI提供
        xmlWriter.writeElementString("ServiceScene", fubon01Header.ServiceScene);//服务场景 描述每个服务的应用场景，由EAI提供,具体在每个服务中说明.如果该服务只有一种使用场景默认值必须为：01
        xmlWriter.writeElementString("InitiatorId", fubon01Header.InitiatorId);//发起方系统编号 移动开户系统：102010
        xmlWriter.writeElementString("ServiceId", fubon01Header.ServiceId);//服务系统编号 （当存在组合交易，填501010，其他情况填服务方编号）
        xmlWriter.writeElementString("TranDate", fubon01Header.TranDate);//前台交易日期 YYYYMMDD
        xmlWriter.writeElementString("TranTime", fubon01Header.TranTime);//前台交易时间 hhmmss
        xmlWriter.writeElementString("ChannelId", "");//渠道节点标识
        xmlWriter.writeElementString("AddChnlId", "");//辅助节点标识
        xmlWriter.writeElementString("AreaCode", "");//地区代码
        xmlWriter.writeElementString("OrgConSeqNo", fubon01Header.OrgConSeqNo);//发起方流水号 全局流水号
        xmlWriter.writeElementString("ConsumerSeqNo", fubon01Header.ConsumerSeqNo);//消费方流水号 调用方产生流水号
        xmlWriter.writeElementString("FileFlag", fubon01Header.FileFlag);//1-有文件，0-无文件
        xmlWriter.writeElementString("FeeFlag", fubon01Header.FeeFlag);//1-收取，0-不收取
        xmlWriter.writeElementString("KeyIndx", "");//密钥索引
        xmlWriter.writeElementString("TranType", "");//交易类型
        xmlWriter.writeElementString("TellerNo", fubon01Header.TellerNo);//柜员号 服务请求者的唯一标识。无法提供柜员号时，缺省为“0000000000”
        xmlWriter.writeElementString("BranchId", fubon01Header.BranchId);//机构代码 服务请求者的机构归属。无法提供机构代码时，缺省为“0000000000”
        xmlWriter.writeEndElement();//GapsAppHead
    }

    protected String[] sendToBankQry(String gxpHeader, String p_reqStr) throws Exception {
        String serviceIP = getBankConfig().getValueAsString("serviceIpQry");
        String servicePort = getBankConfig().getValueAsString("servicePortQry");
        return sendToBank(gxpHeader, p_reqStr, serviceIP, servicePort);
    }

    protected String[] sendToBankPay(String gxpHeader, String p_reqStr) throws Exception {
        String serviceIP = getBankConfig().getValueAsString("serviceIpPay");
        String servicePort = getBankConfig().getValueAsString("servicePortPay");
        return sendToBank(gxpHeader, p_reqStr, serviceIP, servicePort);
    }

    protected String[] sendToBank(String gxpHeader, String p_reqStr, String serverIP, String serverPort) throws Exception {
        byte[] tmpBytesHeader = gxpHeader.getBytes(getCharset());
        int XMLlengthHeader = tmpBytesHeader.length;
        WriteBankLogLn("GXP通讯报文头部长度：" + XMLlengthHeader);
        byte[] tmpBytes = p_reqStr.getBytes(getCharset());
        int XMLlength = tmpBytes.length;
        StringBuilder reqContext = new StringBuilder(p_reqStr).insert(0, String.format("%08d", XMLlength));
        String[] retStr = new String[]{"", ""};
        WriteBankUrlLogLn("请求银行的地址" + serverIP + ":" + serverPort);
        WriteBankLogStep2(reqContext.toString());
        //发送银行前置
        TcpPortClient tmpClient = new TcpPortClient(serverIP, Integer.parseInt(serverPort), this);
        TcpReceiver tmpReceiver = tmpClient.sendMessage(reqContext.toString().getBytes(getCharset()));
        retStr[0] = tmpReceiver.connState;
        retStr[1] = tmpReceiver.getFullString(getCharset());
        if (retStr[1].indexOf("<service>") != -1) {
            retStr[1] = retStr[1].substring(retStr[1].indexOf("<service>"));
        } else {
            retStr[1] = retStr[1];
        }

        WriteBankLogStep3(retStr[1]);
        return retStr;
    }

    /**
     * 发送并获取返回
     *
     * @return 响应JOSN
     * @throws Exception 服务器请求异常
     */
    public String[] sendToBank2(String tmpReqMsg) throws Exception {
        String url = bankFront.serverURL;
        String[] retStr = new String[]{"", ""};
        WriteBankLogStep2(tmpReqMsg);
        SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
        sslContext.init(null, null, null);
        SSLContext.setDefault(sslContext);
        HttpClient httpClient = new HttpClient();
        PostMethod postMethod = new PostMethod(url);
        httpClient.getParams().setParameter(HttpConnectionParams.CONNECTION_TIMEOUT, 10000);
        httpClient.getParams().setParameter(HttpConnectionParams.SO_TIMEOUT, 10000);
        // 构建消息实体
        StringRequestEntity requestEntity = new StringRequestEntity(tmpReqMsg, "application/json", getCharset());
        postMethod.setRequestEntity(requestEntity);
        // 发送Json格式的数据请求
        int result = httpClient.executeMethod(postMethod);

        if (HttpStatus.SC_OK != result) {
            retStr[0] = "MessageHandlerService sendMessage fail";
        } else {
            retStr[1] = postMethod.getResponseBodyAsString();
            WriteBankLogStep3(retStr[1]);
        }

        return retStr;
    }

    /**
     * 写入文件
     *
     * @param content
     * @param fullName
     * @return
     */
    protected boolean exportContentToFile(String content, String fullName) {
        if (StringHelper.isNullOrEmpty(content) || StringHelper.isNullOrEmpty(fullName)) {
            return false;
        }
        try {
            FileHelper.writeFile(fullName, content, "UTF-8");
            WriteBankLogLn2("写入文件：" + fullName + ",文件内容 \r\n" + content);
        } catch (Exception e) {
            WriteBankLogLn2("写入文件：" + fullName + "失败!");
            e.printStackTrace();
            return false;
        }
        return FileHelper.existFile(fullName);
    }

    /**
     * 获取本机IP地址
     *
     * @return
     */
    public String getIpAddress() {
        try {
            Enumeration<NetworkInterface> allNetInterfaces = NetworkInterface.getNetworkInterfaces();
            InetAddress ip = null;
            while (allNetInterfaces.hasMoreElements()) {
                NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
                if (netInterface.isLoopback() || netInterface.isVirtual() || !netInterface.isUp()) {
                    continue;
                } else {
                    Enumeration<InetAddress> addresses = netInterface.getInetAddresses();
                    while (addresses.hasMoreElements()) {
                        ip = addresses.nextElement();
                        if (ip != null && ip instanceof Inet4Address) {
                            return ip.getHostAddress();
                        }
                    }
                }
            }
        } catch (Exception e) {
            WriteBankLogLn2("IP地址获取失败" + e.toString());
        }
        return "";
    }

    protected String getCharset() {
        return getBankConfig().getCharset("gbk");
    }

    @Override
    public void getContentLength(TcpReceiver p_receiver) throws Exception {
        if (p_receiver.contentLength == -1) {
            String tmpCharset = getCharset();
            String tmpRecNow = new String(p_receiver.recBytes, 0, p_receiver.readedLength, tmpCharset);
            if (tmpRecNow.contains("</service>")) {
                p_receiver.contentLength = p_receiver.readedLength;
                p_receiver.contentStartIndex = 0;
            }
        }
    }
}
